package com.ruoyi.asms.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import com.ruoyi.asms.controller.AsmsOwnMaintenanceDeptController;
import com.ruoyi.asms.domain.*;
import com.ruoyi.asms.domain.vo.ThisMonthFaultVo;
import com.ruoyi.asms.domain.vo.ThisMonthInspectionVo;
import com.ruoyi.asms.domain.vo.ThisWeekFaultSQLVo;
import com.ruoyi.asms.domain.vo.ThisWeekFaultVo;

import com.ruoyi.common.core.domain.AsmsAssetFullInfo;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.statistics.vo.NewPieChartVo;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.SecurityUtils;

import com.ruoyi.system.controller.SysDeptController;
import com.ruoyi.system.controller.SysUserController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class AsmsDataStatisticsServiceImpl implements IAsmsDataStatisticsService {

    @Autowired
    private IAsmsAssetFullInfoService assetFullInfoService;
    @Autowired
    private IAsmsFaultAssetService asmsFaultAssetService;
    @Autowired
    private IInspectionTaskService inspectionTaskService;
    @Autowired
    private IAsmsFaultService asmsFaultService;
    @Autowired
    private AsmsReusingService asmsReusingService;

    @Autowired
    private SysDeptController remoteDeptService;
    @Autowired
    private SysUserController remoteUserService;
    @Autowired
    private IAsmsFaultConfirmStageService confirmStageService;
    @Autowired
    private IInspectionService inspectionService;
    @Autowired
    private AsmsOwnMaintenanceDeptController ownMaintenanceDeptController;

    @Override
    public Integer mAssetNum() {
        long count = assetFullInfoService.count(new QueryWrapper<AsmsAssetFullInfo>()
                .eq(AsmsAssetFullInfo.MAINTENANCE_DEPT_ID, SecurityUtils.getDeptId()));
        return (int) count;
    }

    @Override
    public Integer solveFaultNum() {
        long count = asmsFaultAssetService.count(new QueryWrapper<AsmsFaultAsset>().eq(AsmsFaultAsset.IS_FINISH, 0)
                .eq(AsmsFaultAsset.MAINTENANCE_DEPT_ID, SecurityUtils.getDeptId()));
        return (int) count;
    }

    @Override
    public Integer inspectionNum() {
        long count = inspectionTaskService.count(new QueryWrapper<InspectionTask>().eq(InspectionTask.STATUS, 3)
                .eq(InspectionTask.MAINTENANCE_DEPT_ID, SecurityUtils.getDeptId()));
        return (int) count;
    }

    @Override
    public Integer todayFaultNum() {
        long count = asmsFaultService.count(new QueryWrapper<AsmsFault>()
                .gt(AsmsFault.CREATE_TIME, asmsReusingService.getTodayStartTime())
                .lt(AsmsFault.CREATE_TIME, System.currentTimeMillis()));
        return (int) count;
    }

    @Override
    public Integer todayInspectionNum() {
        long count = inspectionTaskService.count(new QueryWrapper<InspectionTask>()
                .eq(InspectionTask.MAINTENANCE_DEPT_ID, SecurityUtils.getDeptId())
                .gt(InspectionTask.CREATE_TIME, asmsReusingService.getTodayStartTime())
                .lt(InspectionTask.CREATE_TIME, System.currentTimeMillis()));
        return (int) count;
    }

    @Override
    public Integer todayBindAssetNum() {
        long count = assetFullInfoService.count(new QueryWrapper<AsmsAssetFullInfo>()
                .gt(AsmsAssetFullInfo.BIND_TIME, asmsReusingService.getTodayStartTime())
                .lt(AsmsAssetFullInfo.BIND_TIME, System.currentTimeMillis()));
        return (int) count;
    }

    @Override
    public List<List<ThisWeekFaultVo>> thisWeekFault(Integer faultOrInsp) {
        List<List<ThisWeekFaultVo>> result = new ArrayList<>();
        //获取上周的开始时间
        Calendar calendar1 = Calendar.getInstance();
        calendar1.setTime(new Date());
        calendar1.add(Calendar.WEEK_OF_YEAR, -1);
        calendar1.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        calendar1.set(Calendar.HOUR_OF_DAY, 0);
        calendar1.set(Calendar.MINUTE, 0);
        calendar1.set(Calendar.SECOND, 0);
        Long lastWeekStartTimeMs = calendar1.getTimeInMillis();

        //获取上周的结束时间（也就是本周的开始时间）
        Calendar calendar2 = Calendar.getInstance();
        calendar2.setTime(new Date());
        calendar2.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        calendar2.set(Calendar.HOUR_OF_DAY, 0);
        calendar2.set(Calendar.MINUTE, 0);
        calendar2.set(Calendar.SECOND, 0);
        Long lastWeekEndTimeMs = calendar2.getTimeInMillis();

        List<ThisWeekFaultSQLVo> lastWeekFault;
        List<ThisWeekFaultSQLVo> thisWeekFault;
        List<ThisWeekFaultVo> lastWeekResult = new ArrayList<>();
        List<ThisWeekFaultVo> thisWeekResult = new ArrayList<>();
        HashMap<Integer, Integer> lastMap = new HashMap<>();
        HashMap<Integer, Integer> thisMap = new HashMap<>();

        String[] weekDayArr = {"周一", "周二", "周三", "周四", "周五", "周六", "周日"};

        if (faultOrInsp.equals(0)) {
            //查故障的处理情况
            lastWeekFault = asmsFaultAssetService
                    .getOneWeekFaultNum(lastWeekStartTimeMs, lastWeekEndTimeMs, SecurityUtils.getDeptId());
            thisWeekFault = asmsFaultAssetService
                    .getOneWeekFaultNum(lastWeekEndTimeMs, System.currentTimeMillis(), SecurityUtils.getDeptId());
        } else {
            //查巡检的处理情况
            lastWeekFault = inspectionTaskService
                    .getOneWeekInspectionNum(lastWeekStartTimeMs, lastWeekEndTimeMs, SecurityUtils.getDeptId());
            thisWeekFault = inspectionTaskService
                    .getOneWeekInspectionNum(lastWeekEndTimeMs, System.currentTimeMillis(), SecurityUtils.getDeptId());
        }
        //上周处理的故障或巡检
        lastWeekFault.forEach(item -> lastMap.put(item.getWeekday(), item.getNum()));
        //本周处理的故障或巡检
        thisWeekFault.forEach(item -> thisMap.put(item.getWeekday(), item.getNum()));

        for (int i = 0; i < weekDayArr.length; i ++) {
            ThisWeekFaultVo vo1 = new ThisWeekFaultVo();
            vo1.setWeekday(weekDayArr[i]);
            if (i != weekDayArr.length -1)
                vo1.setNum(lastMap.get(i + 1) != null ? lastMap.get(i + 1) : 0);
            else
                vo1.setNum(lastMap.get(0) != null ? lastMap.get(0) : 0);
            lastWeekResult.add(vo1);

            ThisWeekFaultVo vo2 = new ThisWeekFaultVo();
            vo2.setWeekday(weekDayArr[i]);
            if (i != weekDayArr.length -1)
                vo2.setNum(thisMap.get(i + 1) != null ? thisMap.get(i + 1) : 0);
            else
                vo2.setNum(thisMap.get(0) != null ? thisMap.get(0) : 0);
            thisWeekResult.add(vo2);
        }
        result.add(lastWeekResult);
        result.add(thisWeekResult);
        return result;
    }

    @Override
    public ThisMonthFaultVo thisMonthFault() {
        ThisMonthFaultVo thisMonthFaultVo = new ThisMonthFaultVo();
        //查询本公司维护的所有学校的故障处理情况
        R<HashSet<Long>> remoteResult =ownMaintenanceDeptController.getODeptIdsByMDeptId(SecurityUtils.getDeptId());
        if (remoteResult.getCode() == R.FAIL)
            throw new ServiceException("系统异常：远程调用出错！");
        HashSet<Long> ownDeptIds = remoteResult.getData();
        if (ownDeptIds.size() == 0)
            return thisMonthFaultVo;
        //查看学校本月的故障情况
        List<AsmsFaultAsset> faultAssets = asmsFaultAssetService.list(new QueryWrapper<AsmsFaultAsset>()
                .select(AsmsFaultAsset.OWN_DEPT_ID, AsmsFaultAsset.IS_FINISH, AsmsFaultAsset.FAULT_RESOLVE_USER_ID,
                        AsmsFaultAsset.FAULT_ASSET_ID)
                .in(AsmsFaultAsset.OWN_DEPT_ID, ownDeptIds)
                .gt(AsmsFaultAsset.CREATE_TIME, asmsReusingService.getThisMonthStartTime())
                .lt(AsmsFaultAsset.CREATE_TIME, System.currentTimeMillis()));
        //查询学校信息
        R<List<SysDept>> deptListByIds = remoteDeptService.getDeptListByIds(ownDeptIds);
        if (deptListByIds.getCode() == R.FAIL)
            throw new ServiceException("系统异常：远程调用出错！");
        List<SysDept> sysDepts = deptListByIds.getData();
        //构造学校故障情况的数据
        List<ThisMonthFaultVo.DeptFaultVo> deptFaultVos = new ArrayList<>();
        for (SysDept sysDept : sysDepts) {
            ThisMonthFaultVo.DeptFaultVo deptFaultVo = new ThisMonthFaultVo.DeptFaultVo();
            int faultNum = 0;
            int unResovleNum = 0;
            for (AsmsFaultAsset faultAsset : faultAssets) {
                if (faultAsset.getOwnDeptId().equals(sysDept.getDeptId())) {
                    faultNum ++;
                    if (faultAsset.getIsFinish() != null && faultAsset.getIsFinish().equals(1))
                        unResovleNum ++;
                }
            }
            deptFaultVo.setDeptName(sysDept.getDeptFullName());
            deptFaultVo.setFaultNum(faultNum);
            deptFaultVo.setUnResovleFaultNum(unResovleNum);
            deptFaultVos.add(deptFaultVo);
        }
        deptFaultVos.sort(Comparator.comparing(ThisMonthFaultVo.DeptFaultVo::getFaultNum).reversed());
        thisMonthFaultVo.setDeptFaults(deptFaultVos);

        //构造维修人员处理故障数量的数据
        R<List<SysUser>> resovlersByDeptId = remoteUserService.getResovlersByDeptId(SecurityUtils.getDeptId());
        if (resovlersByDeptId.getCode() == R.FAIL)
            throw new ServiceException("系统异常：远程调用出错！");
        List<SysUser> resovlers = resovlersByDeptId.getData();

        List<NewPieChartVo> resovlerFaultNum = new ArrayList<>();
        for (SysUser resovler : resovlers) {
            int resovleNum = 0;
            for (AsmsFaultAsset faultAsset : faultAssets) {
                if (faultAsset.getFaultResolveUserId() != null &&
                        faultAsset.getFaultResolveUserId().equals(resovler.getUserId()))
                    resovleNum ++;
            }
            NewPieChartVo newPieChartVo = new NewPieChartVo();
            newPieChartVo.setName(resovler.getNickName());
            newPieChartVo.setValue(resovleNum);
            resovlerFaultNum.add(newPieChartVo);
        }
        resovlerFaultNum.sort(Comparator.comparing(NewPieChartVo::getValue).reversed());
        thisMonthFaultVo.setResovlerFaultNum(resovlerFaultNum);

        //故障总数
        thisMonthFaultVo.setTotalFaultNum(faultAssets.size());

        //未处理故障总数
        int totalUnResovleNum = 0;
        HashSet<Long> faultAssetIds = new HashSet<>();
        for (AsmsFaultAsset faultAsset : faultAssets) {
            faultAssetIds.add(faultAsset.getFaultAssetId());
            if (faultAsset.getIsFinish() != null && faultAsset.getIsFinish().equals(1))
                totalUnResovleNum ++;
        }
        thisMonthFaultVo.setTotalUnResovleFaultNum(totalUnResovleNum);

        //差评数量
        if (faultAssetIds.size() == 0) {
            thisMonthFaultVo.setBadAppraiseNum(0);
        } else {
            long count = confirmStageService.count(new QueryWrapper<AsmsFaultConfirmStage>()
                    .eq(AsmsFaultConfirmStage.ATTITUDE_SCORE, 1)
                    .eq(AsmsFaultConfirmStage.EFFICIENCY_SCORE, 1)
                    .eq(AsmsFaultConfirmStage.QUALITY_SCORE, 1)
                    .in(AsmsFaultConfirmStage.FAULT_ASSET_ID, faultAssetIds));
            thisMonthFaultVo.setBadAppraiseNum((int) count);
        }

        return thisMonthFaultVo;
    }

    @Override
    public ThisMonthInspectionVo thisMonthInspection() {
        ThisMonthInspectionVo thisMonthInspectionVo = new ThisMonthInspectionVo();
        //巡检结果情况
        R<HashSet<Long>> remoteResult = ownMaintenanceDeptController.getODeptIdsByMDeptId(SecurityUtils.getDeptId());
        if (remoteResult.getCode() == R.FAIL)
            throw new ServiceException("系统异常：远程调用出错！");
        HashSet<Long> ownDeptIds = remoteResult.getData();

        if (ownDeptIds.size() == 0)
            return thisMonthInspectionVo;

        R<List<SysDept>> deptListByIds = remoteDeptService.getDeptListByIds(ownDeptIds);
        if (deptListByIds.getCode() == R.FAIL)
            throw new ServiceException("系统异常：远程调用出错！");
        List<SysDept> deptList = deptListByIds.getData();

        List<InspectionTask> inspectionTasks = inspectionTaskService.list(new QueryWrapper<InspectionTask>()
                .select(InspectionTask.STATUS, InspectionTask.ASSET_OWN_IDS)
                .eq(InspectionTask.MAINTENANCE_DEPT_ID, SecurityUtils.getDeptId())
                .gt(InspectionTask.CREATE_TIME, asmsReusingService.getThisMonthStartTime())
                .lt(InspectionTask.CREATE_TIME, System.currentTimeMillis()));

        List<ThisMonthInspectionVo.InspectionResultVo> inspectionResultVos = new ArrayList<>();
        for (SysDept sysDept : deptList) {
            ThisMonthInspectionVo.InspectionResultVo inspectionResultVo = new ThisMonthInspectionVo.InspectionResultVo();
            inspectionResultVo.setDeptName(sysDept.getDeptFullName());
            int deptInspectionNum = 0;
            int unResovleNum = 0;
            for (InspectionTask inspectionTask : inspectionTasks) {
                if (inspectionTask.getAssetOwnIds() != null &&
                        inspectionTask.getAssetOwnIds().contains(sysDept.getDeptId().toString())) {
                    deptInspectionNum ++;
                    if (inspectionTask.getStatus() != null && !inspectionTask.getStatus().equals(3))
                        unResovleNum ++;
                }
            }
            inspectionResultVo.setDeptInspectionNum(deptInspectionNum);
            inspectionResultVo.setUnResovleNum(unResovleNum);
            inspectionResultVos.add(inspectionResultVo);
        }
        inspectionResultVos.sort(Comparator.comparing(ThisMonthInspectionVo.InspectionResultVo::getUnResovleNum).reversed());
        thisMonthInspectionVo.setInspectionResult(inspectionResultVos);

        //巡检人员巡检情况
        R<List<SysUser>> listR = remoteUserService.getInspectionUsersByDeptId(SecurityUtils.getDeptId());
        if (listR.getCode() == R.FAIL)
            throw new ServiceException("系统异常：远程调用出错！");
        List<SysUser> inspecters = listR.getData();

        List<NewPieChartVo> newPieChartVos = new ArrayList<>();
        for (SysUser inspecter : inspecters) {
            NewPieChartVo newPieChartVo = new NewPieChartVo();
            newPieChartVo.setName(inspecter.getNickName());
            int resovleNum = 0;
            for (InspectionTask inspectionTask : inspectionTasks) {
                if (inspectionTask.getInspectionUserIds() != null &&
                        inspectionTask.getInspectionUserIds().contains(inspecter.getUserId().toString()))
                    resovleNum ++;
            }
            newPieChartVo.setValue(resovleNum);
            newPieChartVos.add(newPieChartVo);
        }
        newPieChartVos.sort(Comparator.comparing(NewPieChartVo::getValue).reversed());
        thisMonthInspectionVo.setInspecterSituation(newPieChartVos);

        //巡检任务总数
        thisMonthInspectionVo.setTotalInspectionNum(inspectionTasks.size());

        //未处理数量
        int totalUnResovleNum = 0;
        HashSet<Long> inspectionTaskIds = new HashSet<>();
        for (InspectionTask inspectionTask : inspectionTasks) {
            inspectionTaskIds.add(inspectionTask.getInspectionTaskId());
            if (inspectionTask.getStatus() != null && !inspectionTask.getStatus().equals(3))
                totalUnResovleNum ++;
        }
        thisMonthInspectionVo.setTotalUnResovleNum(totalUnResovleNum);

        //异常数量
        if (inspectionTaskIds.size() == 0) {
            thisMonthInspectionVo.setExceptionNum(0);
            return thisMonthInspectionVo;
        }
        long count = inspectionService.count(new QueryWrapper<Inspection>()
                .in(Inspection.INSPECTION_TASK_ID, inspectionTaskIds).ne(Inspection.RESULT_TYPE, 0));
        thisMonthInspectionVo.setExceptionNum((int) count);

        return thisMonthInspectionVo;
    }
}
